home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
util
/
pack
/
xpkrdcn.lha
/
xpkRDCN
/
decompr.asm
< prev
next >
Wrap
Assembly Source File
|
1992-12-12
|
4KB
|
141 lines
;---------------------------------------------------------------------------;
; ;
; This is the Ross Data Compression implemented in 68000 assembler ;
; by Niklas Sjöberg, 2:203/415.3@Fidonet ;
; ;
; ;
; The source is fully in the Public Domain. If you think you can improve ;
; some parts, feel free to modify the code. HOWEVER, be carefull to comment ;
; the parts where you change! ;
; ;
; On entry: ;
; a0 points to XpkSubParams ;
;---------------------------------------------------------------------------;
; 921205 - Due to optimization comments may seem a bit weird.. Just try
; to read 5-10 lines at the time I'm sure you'll get it right..
xdef _unpack ; The only function called from
; the C-part of the library
INCLUDE "libraries/xpksub.i"
section code
_unpack
movem.l a2-a6/d2-d7,-(SP)
move.l xsp_InBuf(a0),a1 ; source pointer
move.l xsp_InLen(a0),d1 ; source len
move.l xsp_OutBuf(a0),a2 ; destination
move.l a1,a3 ; inbuff_idx = inbuff
move.l a2,a4 ; outbuff_idx = outbuff
move.l a1,a5 ; inbuff_end = inbuff
adda.l d1,a5 ; + inbuff_len
moveq #0,d0
moveq #0,d2
moveq #0,d3
moveq #0,d4
moveq #0,d5
moveq #0,d6
moveq #0,d7
mloop
subq.b #1,d3
; lsr.w #1,d3 ; Check if we need to get a load of
; control bits
bpl.s no_ctrlbits
move.w (a3)+,d2 ; new load ctrl-bits
;
moveq #15,d3 ; ctrl_mask = 0x8000
; This is ugly. Since (in worst case) we may overrun the buffer by
; 15 bytes by not checking source and source-end. However, empty
; control-word means that we only copy 15 in worst case. Hell, we
; have 256 XPK_MARGIN bytes to play with :=) (I hope...)
cmp.l a5,a3 ; main-loop. Go on until end of
bge.w loopend ; source buffer
no_ctrlbits
; First we have to check if data is
; compressed
; move.w d2,d7 ; If bits & mask turns out to be one
; and.w d3,d7 ; then data is compressed
btst d3,d2
bne.s crunched ; char is crunched
move.b (a3)+,(a4)+ ; otherwise, copy char and advance
bra.s mloop ;
crunched
moveq #0,d4 ; First find out what compressions method
; that was used.
move.b (a3)+,d4 ; d4 will eventually contain 0-15
move.w d4,d5 ; d5, contains count (further count may
and.b #$f,d5 ; be needed for some methods.
lsr.b #4,d4 ; The higher 4 bits of d4 is type, and
; and.w #$f,d4 ; the lower count
cmpi.b #2,d4 ; cmd > 2 then it's a short pattern
bls.s no_spat ; (3-15)
; move.w d5,d6 ; count is 3 chars higher actually
addq.b #3,d5 ; d5 is never >15+3
moveq #0,d7 ; to use d4 as loop-register
move.b (a3)+,d7 ; decode offset
asl.w #4,d7
add.w d5,d7
move.l a4,a6 ; Next copy d4 characters from a6
sub.l d7,a6 ; to a4
subq.b #1,d4
s_loop move.b (a6)+,(a4)+ ;
dbf d4,s_loop
bra.s mloop ; Jump to main loop
no_spat tst.b d4
;cmpi.b #0,d4 ;is it short rle?
bne.s no_srle
addq.b #2,d5 ; cnt += 3 (-1 for dbf loop)
move.b (a3)+,d7 ; char to repeat d5 times
sr_loop move.b d7,(a4)+ ;
dbf d5,sr_loop
bra.s mloop ; Main loop
no_srle cmpi.b #1,d4 ; is it a long rle?
bne.s no_lrle
moveq #0,d7
move.b (a3)+,d7 ; if so, decode high/low count
asl.w #4,d7 ; and add them since long RLE
add.w d7,d5 ; is least 19 :
addi.w #18,d5 ; cnt +=19 (-1 for dbf loop)
move.b (a3)+,d7 ; char to set
lr_loop move.b d7,(a4)+ ;
dbf d5,lr_loop
bra.s mloop ; Main loop
no_lrle ; only one case left, long pattern
move.w d5,d6 ;
addq.w #3,d6 ; at least 3 chars long pattern
moveq #0,d7
move.b (a3)+,d7 ; Decode and add high and low
asl.w #4,d7 ; offset
add.w d7,d6 ;
moveq #0,d5
move.b (a3)+,d5 ; Next, get count
addi.w #15,d5 ; which is at least 16 (-1 for loop)
move.l a4,a6 ; source
sub.l d6,a6 ; destination
rl_loop move.b (a6)+,(a4)+
dbf d5,rl_loop
bra.w mloop
loopend
suba.l a2,a4 ; This is the only exit point
move.l a4,xsp_OutBufLen(a0) ; return length to xpkmaster
movem.l (SP)+,a2-a6/d2-d7
moveq #0,d0
rts
END